package cn.itcast.hotel;

import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;
import java.util.Map;

@SpringBootTest
public class HotelIndexTest {

    RestHighLevelClient client = null;

    @BeforeEach
    public void init() {
        client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.248.131", 9200, "http")));
    }

//    @Test
    //创建索引库
    /*void createIndex() throws Exception {
        CreateIndexRequest request = new CreateIndexRequest("twitter");
        request.mapping(
                "{\n" +
                        "  \"properties\": {\n" +
                        "    \"message\": {\n" +
                        "      \"type\": \"text\"\n" +
                        "    }\n" +
                        "  }\n" +
                        "}",
                XContentType.JSON);
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }
*/

//  ---------------------------------------重点掌握代码---------------------------------------

    @Autowired
    private IHotelService hotelService;
    //    1.新增或修改文档
    @Test
    public void testAddOrUpdate()throws Exception{
//        1.查询一个酒店数据  例如：id:36934
        Hotel hotel = hotelService.getById(36934);
//        2. 把hotel对象转成HotelDoc
        HotelDoc hotelDoc = new HotelDoc(hotel);
//        3.参考官网代码
        IndexRequest request = new IndexRequest("hotel");  // ES索引库的名字
        request.id(hotel.getId().toString());
        String jsonString = JSON.toJSONString(hotelDoc);
        request.source(jsonString, XContentType.JSON);
//        4.发起请求
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(indexResponse));
    }


    //    2.修改文档  忽略
    @Test
    public void testUpdate()throws Exception{
        //        1.查询一个酒店数据  例如：id:36934
        Hotel hotel = hotelService.getById(36934);
//        2. 把hotel对象转成HotelDoc
        HotelDoc hotelDoc = new HotelDoc(hotel);
        hotelDoc.setName("修改后新的酒店名字");
//        3.参考官网代码
        UpdateRequest request = new UpdateRequest("hotel", "36934");
        String jsonString = JSON.toJSONString(hotelDoc);
        request.doc(jsonString, XContentType.JSON);
//        4.发起请求
        UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(updateResponse));
    }
    //    3.根据ID查询文档
    @Test
    public void testGetById()throws Exception{
        GetRequest getRequest = new GetRequest("hotel", "36934");
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
//        System.out.println(JSON.toJSONString(getResponse));
//        System.out.println("---------------------------------");
//        System.out.println(getResponse.getSourceAsString());

        HotelDoc hotelDoc = JSON.parseObject(getResponse.getSourceAsString(), HotelDoc.class);
        System.out.println(hotelDoc);
    }
    //    4.根据ID删除文档
    @Test
    public void testDel()throws Exception{
        DeleteRequest deleteRequest = new DeleteRequest("hotel", "36934");
        DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
    }

    //    5. 把tb_hotel表中的数据全部初始化到ES中
    @Test
    public void testBulkAdd()throws Exception{
//        1.查询所有的酒店数据
        List<Hotel> list = hotelService.list();
//    2.创建一个批量请求的对象
        BulkRequest bulkRequest = new BulkRequest();
//    3.向bulkRequest中放数据
        for (Hotel hotel : list){
            HotelDoc hotelDoc = new HotelDoc(hotel);
            bulkRequest.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));
        }
        client.bulk(bulkRequest, RequestOptions.DEFAULT);
    }


    //--------------------------------ES第二天-----------------------------------------
    @Test
    public void testQuery()throws Exception{
        SearchRequest searchRequest = new SearchRequest("hotel");
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//        searchRequest.source(searchSou rceBuilder);

//        searchRequest.source().query(QueryBuilders.matchAllQuery());  //查询所有
//        searchRequest.source().query(QueryBuilders.termQuery("all","如家酒店"));  //查询term  查不出来，没有分词
//        searchRequest.source().query(QueryBuilders.matchQuery("all","如家酒店"));  //match查询
//        searchRequest.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(200));  //区间查询
        searchRequest.source().query(QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("name","如家"))
                .filter(QueryBuilders.rangeQuery("price").gte(100).lte(200)));  //复合查询
        //排序
        searchRequest.source().sort("price", SortOrder.ASC);//升序
        //分页
//        searchRequest.source().from(10);  //查第二页 有7条
        searchRequest.source().from(0);  //查第一页 有10条
        searchRequest.source().size(10);
        //高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        highlightBuilder.requireFieldMatch(false);  //这句话加不加取决于   查询的域名和高亮的域名一致不,一样可以不加
        searchRequest.source().highlighter(highlightBuilder);

        //发送请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        //解析响应
        handlerResponse(searchResponse);
    }

    private void handlerResponse(SearchResponse searchResponse) {
        // 解析响应
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询出来的总条数："+searchHits.getTotalHits().value);
        //文档数组
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            // 获取文档source
            String sourceAsString = hit.getSourceAsString();
            // json字符串反序列化成对象
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);

            // 处理高亮的结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields !=null) {
                HighlightField highlightField = highlightFields.get("name");
                Text[] fragments = highlightField.getFragments();
                if (fragments!=null && fragments.length>0) {
                    String nameHighLight = fragments[0].toString();
                    hotelDoc.setName(nameHighLight);
                }
            }


            System.out.println(hotelDoc);
        }
    }


}
